import { action, makeObservable, observable, runInAction } from 'mobx';

import WithCommonStore from 'Core/common/WithCommonStore';
import WithCommonModel, { WithCommonModelIndex } from 'Models/common/WithCommonModel';

import type { ActionRequestCanceler } from 'Typings/common';

/**
 * `wrapper class` for **common table** store
 * @props detailData the data of the detail for the **table row**
 * @props getDetailRequesting the `request status` of detail data
 * @props detailActionRequesting the `request status` of detail action
 * @function getDetailCanceler the `axios request canceler` of detail data
 * @function getDetailActionCanceler the `axios request canceler` of detail data
 * @function destoryDetailData `clear` the `data` of the **table row detail**
 * @function destoryDetail `clear` the `data` of the **table row detail** related
 * @function setDetailData `set` the data of the `detail`
 * @return `Class WithDetailData`
 */
class WithDetailData<Model extends WithCommonModel, Form = void> extends WithCommonStore {
    @observable detailId: Model[WithCommonModelIndex.ID] = undefined;

    @observable detailData?: Model;

    @observable getDetailRequesting = true;

    @observable.ref getDetailCanceler: ActionRequestCanceler = () => {};

    @observable detailActionRequesting = true;

    @observable.ref getDetailActionCanceler: ActionRequestCanceler = () => {};

    @observable defaultUpdateFormData: Form = {} as Form;

    @observable updateFormData: Form = {} as Form;

    @observable updateRequesting = false;

    @observable.ref updateCanceler: ActionRequestCanceler = () => {};

    constructor() {
        super();
        makeObservable(this);
    }

    @action destoryDetail: NoneParamsAndReturnFuc = () => {
        runInAction(() => {
            this.destoryDetailData();
            this.destoryUpdate();
        });
    };

    @action destoryUpdate: NoneParamsAndReturnFuc = () => {
        runInAction(() => {
            this.destoryUpdateFormData();

            this.updateRequesting = false;
            this.updateCanceler = () => {};
        });
    };

    @action destoryDetailData: WithReturnFuc<[Model?], unknown> = data => {
        runInAction(() => {
            this.setDetailId(undefined);
            this.setDetailData(data ?? ({} as Model));

            this.getDetailRequesting = true;
            this.getDetailCanceler = () => {};
            this.detailActionRequesting = true;
            this.getDetailActionCanceler = () => {};
        });
    };

    @action destoryUpdateFormData: WithReturnFuc<[Form?], unknown> = data => {
        runInAction(() => {
            this.defaultUpdateFormData = {} as Form;

            this.setUpdateFormData(data ?? ({} as Form));
        });
    };

    @action setDetailId: WithReturnFuc<[Model[WithCommonModelIndex.ID]], unknown> = data => {
        runInAction(() => {
            this.detailId = data;
        });
    };

    @action setDetailData: WithReturnFuc<[Model], unknown> = data => {
        runInAction(() => {
            this.detailData = data;
            this.setDetailId(this.detailData?.[WithCommonModelIndex.ID] ?? undefined);
        });
    };

    @action setUpdateFormData: WithReturnFuc<[Form], unknown> = data => {
        runInAction(() => {
            this.updateFormData = data;
        });
    };
}

export default WithDetailData;
